/**
 * Copyright (C) © 2014 深圳市掌玩网络技术有限公司
 */

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetSocketAddress;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicBoolean;

/**
 * <p>
 * <strong>Features draft description.主要功能介绍</strong>
 * </p>
 * 
 * @author Administrator
 * @Create at 2015-11-26 上午9:54:33
 * @Version 1.0
 * 
 */
public class UdpTranser {
    ConcurrentHashMap<String, InetSocketAddress> clientList    = new ConcurrentHashMap<String, InetSocketAddress>();
    ConcurrentHashMap<String, Long>              ClientIDLEMap = new ConcurrentHashMap<String, Long>();
    final int                                    TIME_IDLE     = 10 * 1000;
    public Object                                Lock_Remove   = new Object();
    public UdpTranser(DatagramSocket mDatagramSocket) {
        this.mDatagramSocket = mDatagramSocket;
        new Thread() {
            public void run() {
                try {
                    while (true) {
                        sleep(TIME_IDLE);
                        checkClientIDLE();
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            };
        }.start();
    }
    /**
     * 
     */
    protected void checkClientIDLE() {
        Iterator<?> iter = ClientIDLEMap.entrySet().iterator();
        ArrayList<String> need2remove = new ArrayList<String>();
        while (iter.hasNext()) {
            @SuppressWarnings("unchecked")
            Map.Entry<String, Long> entry = (Entry<String, Long>) iter.next();
            String key = (String) entry.getKey();
            Long val = entry.getValue();
            if (System.currentTimeMillis() - val.longValue() > TIME_IDLE) {
                need2remove.add(key);
            }
        }
        synchronized (Lock_Remove) {
            if (need2remove.size()>0) {
                for (String string : need2remove) {
                    ClientIDLEMap.remove(string);
                    clientList.remove(string);
                    System.out.println("user has idle:"+string+" remain:"+ClientIDLEMap.size());
                }
            }
        }

    }

    int            packetCuntInSecond = 0;

    AtomicBoolean  isRunning          = new AtomicBoolean(false);
    DatagramSocket mDatagramSocket;



    public void addSocket(DatagramPacket packet) {
        final InetSocketAddress inetSocketAddress = (InetSocketAddress) packet.getSocketAddress();
        final String addressInfo = getAddressInfo(packet);
        if (!clientList.containsKey(addressInfo)) {
            System.out.println("user join >"+addressInfo );
            clientList.put(addressInfo, inetSocketAddress);
            ClientIDLEMap.put(addressInfo, System.currentTimeMillis());
        }
        tranAsync(packet);
    }

    private String getAddressInfo(DatagramPacket packet) {
        return packet.getAddress().getHostAddress() + packet.getPort();
    }

    byte[] bytes = new byte[10 * 1024];

    private void tranAsync(final DatagramPacket datagramPacket) {
        int read = datagramPacket.getLength();
        if (read<6) {
            System.out.println("pack size <6  is " +read);
			return;
		}
        System.arraycopy(datagramPacket.getData(), 0, bytes, 0, datagramPacket.getLength());
        System.out.println("action "+bytes[6]+" size:"+read);
        if (bytes[6] == 100) {
            System.out.println("recv ping");
            try {
                IOUtil.send(mDatagramSocket, datagramPacket.getAddress(), datagramPacket.getPort(), bytes, 0, read);
            } catch (IOException e) {
                e.printStackTrace();
            }
            return;
        }
        if (bytes[6] == 105) {//input event
        }
        if (bytes[6] == 107) {//gamestart
        	 System.out.println("recv gamestart remain"+clientList.size());
        }
        String hash = getAddressInfo(datagramPacket);

        if (read > 0) {
            synchronized (Lock_Remove) {
                Iterator<?> iter = clientList.entrySet().iterator();
                while (iter.hasNext()) {
                    @SuppressWarnings("unchecked")
                    Map.Entry<String, InetSocketAddress> entry = (Entry<String, InetSocketAddress>) iter.next();
                    String key = (String) entry.getKey();
                    InetSocketAddress val = entry.getValue();
                    if (!hash.equals(key)) {
                        try {
                            System.out.println("tran udp" + ">" + val.getAddress() + ":" + val.getPort());
                            IOUtil.send(mDatagramSocket, val.getAddress(), val.getPort(), bytes, 0, read);
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
        }

    }


}
